/*{
	"DESCRIPTION": "expects a RGBA-format image on 'inputImage'.  the dimensions of the output image will be one-half the width of this input image and one-and-one-half times the height of this input image.  for example, if 'inputImage' is 1000x1000, the output image size (and the size at which this shader should be rendered) is 500x1500",
	"CREDIT": "by zoidberg",
	"ISFVSN": "2",
	"CATEGORIES": [
		"Utility"
	],
	"INPUTS": [
		{
			"NAME": "inputImage",
			"TYPE": "image"
		},
		{
			"NAME": "blackFlag",
			"TYPE": "bool",
			"DEFAULT": 0
		},
		{
			"NAME": "colorType",
			"TYPE": "long",
			"DEFAULT": 2,
			"VALUES": [
				0,
				1,
				2,
				3,
				4,
				5
			],
			"LABELS": [
				"BT.601",
				"Full",
				"BT.709",
				"YPbPrSD",
				"YPbPrHD",
				"T.871 (JFIF)"
			]
		}
	]
	
}*/

//const mat3 matrix = mat3(0.25678823529412, -0.14822352941176, 0.43921568627451, 0.50412941176471, -0.29099215686275, -0.36778823529412, 0.09790588235294, 0.43921568627451, -0.07142745098039);
//const vec4 offsets = vec4(0.50196078431373, 0.06274509803922, 0.50196078431373, 0.06274509803922);

//const mat3 RGB_YCbCr_601_mat = mat3(0.257, -0.148, 0.439, 0.504, -0.291, -0.368, 0.098, 0.439, -0.071);
//const vec4 RGB_YCbCr_601_offsets = vec4(0.50196078431373, 0.06274509803922, 0.50196078431373, 0.06274509803922);
const mat3 RGB_YCbCr_601_mat = mat3(0.257, -0.148, 0.439, 0.504, -0.291, -0.368, 0.098, 0.439, -0.071);
const vec4 RGB_YCbCr_601_offsets = vec4(128., 16., 128., 16.);

//const mat3 RGB_YCbCr_Full_mat = mat3(0.299, -0.169, 0.5, 0.587, -0.331, -0.419, 0.114, 0.5, -0.081);
//const vec4 RGB_YCbCr_Full_offsets = vec4(0.50196078431373, 0.0, 0.50196078431373, 0.0);
const mat3 RGB_YCbCr_Full_mat = mat3(0.299, -0.168736, 0.5, 0.587, -0.331264, -0.418688, 0.114, 0.5, -0.081312);
const vec4 RGB_YCbCr_Full_offsets = vec4(128., 0., 128., 0.);

//const mat3 RGB_YCbCr_709_mat = mat3(0.183, -0.101, 0.439, 0.614, -0.339, -0.399, 0.062, 0.439, -0.040);
//const vec4 RGB_YCbCr_709_offsets = vec4(0.50196078431373, 0.06274509803922, 0.50196078431373, 0.06274509803922);
const mat3 RGB_YCbCr_709_mat = mat3(0.183, -0.101, 0.439, 0.614, -0.339, -0.399, 0.062, 0.439, -0.040);
const vec4 RGB_YCbCr_709_offsets = vec4(128., 16., 128., 16.);

const mat3 RGB_YPbPr_SD_mat = mat3(0.299, -0.169, 0.5, 0.587, -0.331, -0.419, 0.114, 0.5, -0.081);
const vec4 RGB_YPbPr_SD_offsets = vec4(128., 0., 128., 0.);

const mat3 RGB_YPbPr_HD_mat = mat3(0.213, -0.115, 0.5, 0.715, -0.385, -0.454, 0.072, 0.5, -0.046);
const vec4 RGB_YPbPr_HD_offsets = vec4(128., 0., 128., 0.);

void main()	{
	vec4		tmpColor = vec4(0., 0., 0., 1.);
	
	ivec2		renderSize = ivec2(RENDERSIZE.x, RENDERSIZE.y);
	ivec2		imgSize = ivec2(IMG_SIZE(inputImage).x, IMG_SIZE(inputImage).y);
	ivec2		alphaSize = ivec2(renderSize.x, renderSize.y/3);
	ivec2		fragCoord = ivec2(gl_FragCoord.x, gl_FragCoord.y);
	
	//	if this is the YCbCr part of the image
	if (fragCoord.y < imgSize.y)	{
		vec2		srcCoord;
		
		srcCoord = vec2(fragCoord.x*2, imgSize.y - fragCoord.y);
		srcCoord += vec2(0.5, -0.5);
		vec3		rgb0 = (blackFlag) ? vec3(0.) : IMG_PIXEL(inputImage, srcCoord).rgb;
		
		srcCoord = vec2((fragCoord.x*2)+1, imgSize.y - fragCoord.y);
		srcCoord += vec2(0.5, -0.5);
		
		vec3		rgb1 = (blackFlag) ? vec3(0.) : IMG_PIXEL(inputImage, srcCoord).rgb;
		
		//	convert RGB from 0.-1. to 0.-255.
		rgb0 = rgb0 * vec3(255.);
		rgb1 = rgb1 * vec3(255.);
		
		vec3		ycbcr0;
		vec3		ycbcr1;
		if (colorType==0)	{
			ycbcr0 = RGB_YCbCr_601_mat * rgb0;
			ycbcr1 = RGB_YCbCr_601_mat * rgb1;
		}
		else if (colorType==1)	{
			ycbcr0 = RGB_YCbCr_Full_mat * rgb0;
			ycbcr1 = RGB_YCbCr_Full_mat * rgb1;
		}
		else if (colorType==2)	{
			ycbcr0 = RGB_YCbCr_709_mat * rgb0;
			ycbcr1 = RGB_YCbCr_709_mat * rgb1;
		}
		else if (colorType==3)	{
			ycbcr0 = RGB_YPbPr_SD_mat * rgb0;
			ycbcr1 = RGB_YPbPr_SD_mat * rgb1;
		}
		else if (colorType==4)	{
			ycbcr0 = RGB_YPbPr_HD_mat * rgb0;
			ycbcr1 = RGB_YPbPr_HD_mat * rgb1;
		}
		else if (colorType==5)	{
			ycbcr0[0] = clamp((0.299 * rgb0.r) + (0.587 * rgb0.g) + (0.114 * rgb0.b), 0., 255.);
			ycbcr0[1] = clamp( ((-0.299 * rgb0.r) - (0.587 * rgb0.g) + (0.866 * rgb0.b))/1.772 + 128., 0., 255.);
			ycbcr0[2] = clamp( ((0.701 * rgb0.r) - (0.587 * rgb0.g) - (0.114 * rgb0.b))/1.402 + 128., 0., 255.);
		
			ycbcr1[0] = clamp((0.299 * rgb1.r) + (0.587 * rgb1.g) + (0.114 * rgb1.b), 0., 255.);
			ycbcr1[1] = clamp( ((-0.299 * rgb1.r) - (0.587 * rgb1.g) + (0.866 * rgb1.b))/1.772 + 128., 0., 255.);
			ycbcr1[2] = clamp( ((0.701 * rgb1.r) - (0.587 * rgb1.g) - (0.114 * rgb1.b))/1.402 + 128., 0., 255.);
		}
	
		//	this gets the average Cb and Cr for the two pixels (this is the subsampling)
		vec2		cbcr_ss = (ycbcr0.gb + ycbcr1.gb) / 2.0;
	
		vec4		ycbycr;
		ycbycr[3] = ycbcr1[0];	// Y1
		ycbycr[2] = cbcr_ss[0]; // Cb
		ycbycr[1] = ycbcr0[0];	// Y0
		ycbycr[0] = cbcr_ss[1]; // Cr
	
	
		//ycbycr[0] = cbcr_ss[0]; // Cb
		//ycbycr[1] = ycbcr0[0];	// Y0
		//ycbycr[2] = cbcr_ss[1]; // Cr
		//ycbycr[3] = ycbcr1[0];	// Y1
	
		if (colorType==0)	{
			ycbycr += RGB_YCbCr_601_offsets;
		}
		else if (colorType==1)	{
			ycbycr += RGB_YCbCr_Full_offsets;
		}
		else if (colorType==2)	{
			ycbycr += RGB_YCbCr_709_offsets;
		}
		else if (colorType==3)	{
			ycbycr += RGB_YPbPr_SD_offsets;
		}
		else if (colorType==4)	{
			ycbycr += RGB_YPbPr_HD_offsets;
		}
		else if (colorType==5)	{
			//	intentionally blank
		}
	
		gl_FragColor = (ycbycr/vec4(255.));
	}
	//	else if this is the alpha part of the image- every fragment processed here is part of the alpha image
	else	{
		//	the relative coordinate of this fragment in the alpha image.
		ivec2		relFragCoord = ivec2(fragCoord.x, fragCoord.y - imgSize.y);
		//relFragCoord.x = alphaSize.x - 1 - fragCoord.x;
		//relFragCoord.y = alphaSize.y - 1 - relFragCoord.y;
		
		//	a 'fragIndexInAlpha' value of 0 corresponds to the bottom-left corner of the alpha image
		int			fragIndexInAlpha = relFragCoord.x + (relFragCoord.y * renderSize.x);
		//fragIndexInAlpha = (alphaSize.x * alphaSize.y) - 1 - fragIndexInAlpha;
		
		//	a 'fragIndexInSrc' value of 0 corresponds to the top-left corner of the src image.
		int			fragIndexInSrc = fragIndexInAlpha * 4;
		//fragIndexInSrc = (imgSize.x * imgSize.y) - 4 - fragIndexInSrc;
		
		int			baseFragRowInSrc = int(floor(float(fragIndexInSrc)/float(imgSize.x)));
		int			baseFragColInSrc = fragIndexInSrc - (baseFragRowInSrc * imgSize.x);
		
		baseFragRowInSrc = imgSize.y - 1 - baseFragRowInSrc;
		
		//if (baseFragRowInSrc == 0)
		//	gl_FragColor = vec4(1., 0., 0., 1.);
		ivec2		srcCoords[4];
		for (int i=0; i<4; ++i)	{
			ivec2		tmpCoords = ivec2(baseFragColInSrc + i, baseFragRowInSrc);
			while (tmpCoords.x >= imgSize.x)	{
				tmpCoords.x -= imgSize.x;
				tmpCoords.y -= 1;
			}
			srcCoords[i] = tmpCoords;
		}
		vec4		pixelColors[4];
		for (int i=0; i<4; ++i)	{
			vec2		sampleCoords = vec2(srcCoords[i].x, srcCoords[i].y);
			sampleCoords += vec2(0.5);
			pixelColors[i] = IMG_PIXEL(inputImage, sampleCoords);
		}
		
		//	i don't know why, but swapping the R & B coords here is necessary to get the output to work with NDI software.
		
		//gl_FragColor = vec4(pixelColors[0].a, pixelColors[1].a, pixelColors[2].a, pixelColors[3].a);
		gl_FragColor = vec4(pixelColors[2].a, pixelColors[1].a, pixelColors[0].a, pixelColors[3].a);
		
		
		
#if 0
		if (fragIndexInAlpha == 0)
			gl_FragColor = vec4(1., 0., 0., 1.);
		if (fragIndexInAlpha == 1)
			gl_FragColor = vec4(0., 1., 0., 1.);
		if (fragIndexInAlpha == 2)
			gl_FragColor = vec4(0., 0., 1., 1.);
#endif
#if 0
		if (fragIndexInSrc == 88)
			gl_FragColor = vec4(1., 0., 0., 1.);
		if (fragIndexInSrc == 92)
			gl_FragColor = vec4(0., 1., 0., 1.);
		if (fragIndexInSrc == 96)
			gl_FragColor = vec4(0., 0., 1., 1.);
#endif
	}
	
	
}
